package com.tungse.study.single;

/**
 * 单例模式的懒汉式实现
 * 直接创建在类内部声明一个静态对象，
 * 对外提供一个获取该对象的静态方法，当第一次调用getInstance方法时，才创建对象
 *
 * 但是，如果是多线程环境，会出现 线程安全问题。
 * @author Tungse
 */
public class Demo2_LanHanSingleton {


    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                Demo2_LanHanSingleton.getInstance();
            }).start();
        }
    }
    //私有化构造方法
    private Demo2_LanHanSingleton() {
        System.out.println(Thread.currentThread().getName() + "  ===  OK");
    }

    private volatile static Demo2_LanHanSingleton INSTANCE;

    //  1.  线程不安全的实现方式
//    public static Demo2_LanHanSingleton getInstance() {
//        if(INSTANCE == null){
//            INSTANCE = new Demo2_LanHanSingleton();
//        }
//        return INSTANCE;
//    }

    //  2.  线程安全的实现方式 1
//    public static synchronized Demo2_LanHanSingleton getInstance() {
//        if(INSTANCE == null){
//            INSTANCE = new Demo2_LanHanSingleton();
//        }
//        return INSTANCE;
//    }

    //  3.  线程安全的实现方式2  双重锁模式
//    public static synchronized Demo2_LanHanSingleton getInstance() {
//        if(INSTANCE == null){
//            synchronized(Demo2_LanHanSingleton.class){
//                if(INSTANCE == null) {
//                    INSTANCE = new Demo2_LanHanSingleton();
//                }
//            }
//        }
//        return INSTANCE;
//    }

    //  4. 静态内部类  static 修饰的成员变量、内部类、代码块等， 只会在类首次创建时初始化
    private static class  Demo2_LanHanSingletonHandle {
        private static final Demo2_LanHanSingleton INSTANCE = new Demo2_LanHanSingleton();
    }
    public static Demo2_LanHanSingleton getInstance() {
        return Demo2_LanHanSingletonHandle.INSTANCE;
    }

    public void showMessage(){
        System.out.println("Hello World!");
    }
}
